//
//  Address.swift
//  Social
//
//  Created by 李响 on 2019/5/27.
//  Copyright © 2019 shengsheng. All rights reserved.
//

import Foundation

enum Address {
    
    static let list: [Model] = {
        guard let asset = NSDataAsset(name: "citys") else {
            return []
        }
        do {
            return try JSONDecoder().decode([Address.Model].self, from: asset.data)
        } catch {
            return []
        }
    } ()
}

extension Address {
    
    enum Grade {
        case province   // 省(直辖市)
        case city       // 市级
        case county     // 县(区)级
        
        var idx: Int {
            switch self {
            case .province:     return 1
            case .city:         return 2
            case .county:       return 3
            }
        }
    }
    
    static func get(_ grade: Grade, code: Int) -> [String]? {
        return .init(get(names: code)?.prefix(grade.idx) ?? [])
    }
}

extension Address {
    
    static func get(models code: Int) -> [Model]? {
        return recursion { $0.code == "\(code)" }
    }
    static func get(names code: Int) -> [String]? {
        return get(models: code)?.map { $0.name }
    }
    static func get(name code: Int) -> String? {
        return get(names: code)?.joined(separator: " ")
    }
    
    static func get(models name: String) -> [Model]? {
        return recursion { $0.name == name }
    }
    static func get(code name: String) -> Int? {
        return get(models: name)?.last?.code.int
    }
    
    private static func recursion(_ next: [Model] = list,
                                  _ result: [Model] = [],
                                  _ closure: (Model) -> Bool) -> [Model]? {
        for model in next {
            guard !closure(model) else {
                return result + [model]
            }
            guard
                let childs = model.children,
                let result = recursion(childs, result + [model], closure) else {
                continue
            }
            return result
        }
        return nil
    }
}

extension Address {
    
    struct Model: Codable {
        let children: [Model]?
        let code: String
        let name: String
    }
}

